// acetone, 2024
// I hate copyright of any kind. This is a public domain.
// Original source: https://notabug.org/acetone/samty

#include "samserver.h"

Samty::SAMServer::SAMServer(const Configuration &samConfiguration,
                            PendingConnectionCallbackPointer callback)
    : m_streamSession (samConfiguration),
    m_connectionCallback (callback)
{
}

std::string Samty::SAMServer::myAddress() const
{
    const auto ident = m_streamSession.getMyDestination();
    if (not ident.isOk()) return std::string();
    return ident.dest33().empty() ? ident.dest32() : ident.dest33();
}

bool Samty::SAMServer::isOk() const
{
    return not m_streamSession.isSick();
}

std::string Samty::SAMServer::errorString() const
{
    return m_streamSession.errorString();
}

bool Samty::SAMServer::start()
{
    if (m_started.load() or !isOk()) return false;

    m_mainThread = std::thread(&SAMServer::loop, this);

    m_started.store(true);
    return true;
}

void Samty::SAMServer::stop()
{
    if (!m_started.load()) return;

    m_started.store(false);
    m_streamSession.closeSocket();

    if (m_mainThread.joinable())
    {
        m_mainThread.join();
    }
}

void Samty::SAMServer::loop()
{
    while (m_started.load())
    {
        auto acceptResult = m_streamSession.accept(false);
        if (!acceptResult.isOk)
        {
            std::cerr << "Samty::SAMServer::loop() Accept failed" << std::endl;
            continue;
        }

        std::unique_ptr<I2pSocket> socket = std::move(acceptResult.value);

        std::string b32 = socket->readDestination();
        if (b32.empty())
        {
            std::cerr << "Samty::SAMServer::loop() Incoming destination reading failed" << std::endl;
            continue;
        }

        m_connectionCallback(b32, std::move(socket));
    }
}
